# -*- coding: utf-8 -*-
import logging
import os
import random
import time
from traceback import format_exc
from scrapy.utils.project import get_project_settings
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.wait import WebDriverWait
from zc_core.dao.cookie_dao import CookieDao
from zc_core.middlewares.proxies.cached_pool import CachedProxyPool
from zc_core.plugins.verify_code import VerifyCode
from zc_core.util.instance_builder import build_instance

logger = logging.getLogger('login')


class SeleniumLogin(object):
    # 登录地址
    login_url = ''
    cookie_white_list = ['token']

    def __init__(self, timeout=180):
        settings = get_project_settings()
        self.max_login_retry = settings.get('MAX_LOGIN_RETRY', 5)
        self.accounts = settings.get('ACCOUNTS', [])
        self.timeout = timeout

    def new_chrome(self):
        settings = get_project_settings()
        self.option = webdriver.ChromeOptions()
        # self.option.add_argument('--headless')
        self.option.add_argument('--no-sandbox')
        # 构建校验器对象
        proxy_pool_class = settings.get('PROXY_POOL_CLASS', '')
        if proxy_pool_class:
            self.pool = build_instance(proxy_pool_class, settings)
        else:
            self.pool = CachedProxyPool(settings)
        self.option.add_argument('--proxy-server=http://%s' % self.pool.get_proxy())

        self.browser = webdriver.Chrome(chrome_options=self.option)
        self.browser.set_window_size(1400, 700)
        self.browser.set_page_load_timeout(self.timeout)

    def login(self):
        try:
            self.new_chrome()
            self.browser.get(self.login_url)
            account = random.choice(self.accounts)
            logger.info('login account: %s' % account)

            username = self.browser.find_element_by_name("username")
            username.clear()
            username.send_keys(list(account.keys())[0])
            time.sleep(1)

            password = self.browser.find_element_by_name("password")
            password.clear()
            password.send_keys(list(account.values())[0])
            time.sleep(1)

            # 登录
            submit = self.browser.find_element_by_class_name("login-block__button")
            submit.click()
            time.sleep(3)

            # 校验
            WebDriverWait(self.browser, 15).until(EC.presence_of_element_located((By.CLASS_NAME, "avatar-container")))
            cookies = self.browser.get_cookies()
            logger.info('--> cookies: %s' % cookies)

            self.browser.close()
            return cookies
        except Exception as e:
            _ = e
            logger.error(format_exc())
            self.browser.close()
            return list()

    # def _verify_code(self, element):
    #     """
    #     截取指定元素图片
    #     :param element: 元素对象
    #     :return: 无
    #     """
    #     """图片路径"""
    #     settings = get_project_settings()
    #     base_path = os.path.join(settings.get('IMAGES_STORE'), 'verify_code/')
    #     if not os.path.exists(base_path):
    #         os.makedirs(base_path)
    #     file = os.path.join(base_path, '%s.png' % str(time.strftime('%Y%m%d%H%M%S')))
    #     element.screenshot(file)
    #
    #     """保存识别结果"""
    #     # 1004：四位数字英文混合
    #     code = VerifyCode().verify(file, code_type='1004')
    #     if code:
    #         new_file = os.path.join(base_path, '%s.png' % code)
    #         os.rename(file, new_file)
    #         return code

    # cookie获取
    def get_cookies(self):
        cookie_dao = CookieDao()
        cookies = cookie_dao.get_cookie()
        if not cookies:
            cookies = self.__get_cookies(0)
            cookie_dao.save_cookie(cookies, expire_time=5400)
        return cookies

    # 最大重试登录获取cookie
    def __get_cookies(self, retry):
        # 登录获取
        arr = self.login()
        if not arr:
            # 失败重试
            if retry <= self.max_login_retry:
                retry = retry + 1
                logger.info('--> 登录失败重试: %s次' % retry)
                return self.__get_cookies(retry)
            else:
                logger.info('--> 放弃失败重试: %s次' % retry)
                return dict()

        # 重组、白名单过滤
        cookies = dict()
        for cookie in arr:
            cookie_key = cookie.get('name')
            if cookie_key in self.cookie_white_list:
                cookies[cookie_key] = cookie.get('value')

        # 校验
        if not cookies or not self._validate_cookie(cookies):
            # 失败重试
            if retry <= self.max_login_retry:
                retry = retry + 1
                logger.info('--> 登录失败重试: %s次' % retry)
                return self.__get_cookies(retry)
            else:
                logger.info('--> 放弃失败重试: %s次' % retry)
                return dict()

        logger.info('--> 登录成功: %s次' % retry)
        return cookies

    # cookie校验
    def _validate_cookie(self, cookies):
        for must_key in self.cookie_white_list:
            # 必要字段校验
            if not cookies or (must_key not in cookies) or (cookies.get(must_key) is None) or (
                    cookies.get(must_key) is ''):
                logger.info('--> Cookie未通过校验: key=%s, cookie=%s' % (must_key, cookies))
                return False

        return True


if __name__ == '__main__':
    login = SeleniumLogin()
    login.get_cookies()
